package dryven.util.crypt;

import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class AESGeneratedKey {

	private byte[] _key;
	private KeyLength _length;
	
	public AESGeneratedKey(KeyLength length) {
		super();
		_length = length;
	}
	
	public AESGeneratedKey() {
		this(KeyLength.AESHighestAvailable);
	}

	public enum KeyLength {
		AES128(128), 
		AES192(192), 
		AES256(256), 
		AESHighestAvailable(-1);
	
		KeyLength(int l) {_length = l;}
		private int _length;
		public int length() {return _length;}
	}
	
	protected byte[] generate(KeyLength l) {
		KeyGenerator kgen;
		try {
			kgen = KeyGenerator.getInstance("AES");
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("AES not available", e);
		}
		if(l.length()==KeyLength.AESHighestAvailable.length()) {
			KeyLength[] lengths = {KeyLength.AES256,KeyLength.AES192,KeyLength.AES128};
			for (KeyLength keyLength : lengths) {
				if(tryGenerateKeyWithLength(kgen, keyLength.length())) {
					break;
				}
			}
		} else {
			if(!tryGenerateKeyWithLength(kgen, l.length())) {
				throw new InvalidParameterException();
			}
		}
	    // Generate the secret key specs.
	    SecretKey skey = kgen.generateKey();
	    byte[] raw = skey.getEncoded();
	    return raw;
	}
	
	private boolean tryGenerateKeyWithLength(KeyGenerator kgen, int length) {
		try {
			kgen.init(length);
			return true;
		} catch(InvalidParameterException e) {
			return false;
		}
	}
	
	public byte[] getKey() {
		if(_key==null) {
			_key = generate(_length);
		}
		return _key;
	}
}
